Skip to content

Conversation

rodrigopavezi
Copy link
Member

@rodrigopavezi rodrigopavezi commented Sep 24, 2025

Fixes #146

Summary by CodeRabbit

  • New Features

    • Fees now display as USD alongside original values for clearer cost context.
    • Added an info icon that opens a tooltip with a detailed fee breakdown when available.
    • Tooltip activation is isolated from row selection to prevent accidental navigation.
  • Changes

    • Platform fee is no longer shown as a separate inline label; details are available via the tooltip.
    • Popover styling adjusted to improve contrast in light/dark themes.

@rodrigopavezi rodrigopavezi self-assigned this Sep 24, 2025
Copy link
Contributor

coderabbitai bot commented Sep 24, 2025

Walkthrough

Adds feeInUSD and optional feeBreakdown to the PaymentRoute type and updates the PaymentRoute component to show fee in USD with an optional Info tooltip showing a formatted fee breakdown (tooltip click stops propagation). platformFee prop/display removed; native token logic removed.

Changes

Cohort / File(s) Summary
UI: Fee display & tooltip
src/components/payment-route.tsx
Replaced inline/platform fee text with USD feeInUSD display; imported internal Tooltip and Info icon; added formatFeeBreakdown helper; conditionally renders Tooltip when route.feeBreakdown exists; tooltip trigger calls stopPropagation; removed platformFee usage and nativeToken calculation.
Types: PaymentRoute extension
src/lib/types/index.ts
Added feeInUSD: number and optional feeBreakdown?: { type: "gas" | "crosschain" | "platform"; stage: "sending" | "overall"; provider: string; amount: string; amountInUSD: string; amountInGwei?: string | null; currency: string; network: string; rateProvider?: string; receiverAddress?: string; }[] to PaymentRoute.
Minor: formatting / import reorder & CSS
src/app/i/[id]/page.tsx, src/components/dashboard/blocks/invoice-row.tsx, src/components/view-recurring-payments/view-recurring-payments.tsx, src/app/globals.css
Non-functional import reorder and JSX formatting changes; CSS theme variable adjustments for popover colors between light/dark contexts.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UI as PaymentRoute
  participant TT as Tooltip

  User->>UI: View route row
  UI->>UI: Read route.feeInUSD and route.feeBreakdown
  alt feeBreakdown present
    UI->>TT: Render Tooltip (Info icon) with formatted breakdown
    User->>TT: Click Info icon
    note right of UI #f8f3d4: click handler calls stopPropagation
    TT-->>User: Show breakdown content
  else no feeBreakdown
    UI-->>User: Show USD fee only
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • MantisClone
  • aimensahnoun
  • bassgeta

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The changeset includes unrelated modifications such as import reordering in page.tsx and formatting adjustments in invoice-row.tsx and view-recurring-payments.tsx that do not pertain to adding the fee breakdown tooltip feature. Separate or revert formatting-only and import reorder changes into a different pull request to keep this PR focused solely on the fee breakdown tooltip feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly states the primary change of adding a fee breakdown tooltip to the payment route component and accurately reflects the main functionality implemented in the changeset.
Linked Issues Check ✅ Passed The pull request implements the fee breakdown tooltip UI in the payment route component and updates the PaymentRoute type to include feeBreakdown and feeInUSD, fulfilling the requirement from issue #146 to display a fee breakdown before payment.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/fees-breakdown

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/components/payment-route.tsx (1)

75-108: Improve key uniqueness and prep for i18n; optional memoization.

  • Keys can collide if two items share type/provider/stage. Append index.
  • Consider externalizing "Fee Breakdown", "Gas Fee", "Bridge Fee", "Platform Fee" for i18n.
  • Optionally memoize the JSX to avoid recompute on each render.

Apply this minimal key fix:

-        {route.feeBreakdown.map((fee) => (
+        {route.feeBreakdown.map((fee, i) => (
           <div
-            key={`${fee.type}-${fee.provider}-${fee.stage}`}
+            key={`${fee.type}-${fee.provider}-${fee.stage}-${i}`}
             className="flex justify-between items-start text-xs"
           >
src/lib/types/index.ts (1)

12-23: Extract FeeBreakdownItem type and reuse for clarity and reuse.

Keeps PaymentRoute concise and improves ergonomics across the codebase.

Apply this change within the interface:

-  feeBreakdown?: {
-    type: "gas" | "crosschain" | "platform";
-    stage: "sending" | "overall";
-    provider: string;
-    amount: string;
-    amountFormatted: string;
-    amountInGwei?: string | null;
-    currency: string;
-    network: string;
-    rateProvider?: string;
-    receiverAddress?: string;
-  }[];
+  feeBreakdown?: FeeBreakdownItem[];

And add this type near the top of the file:

export type FeeBreakdownItem = {
  type: "gas" | "crosschain" | "platform";
  stage: "sending" | "overall";
  provider: string;
  amount: string;
  amountFormatted: string;
  amountInGwei?: string | null;
  currency: string;
  network: string;
  rateProvider?: string;
  receiverAddress?: string;
};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e18bbf9 and 5231649.

📒 Files selected for processing (2)
  • src/components/payment-route.tsx (3 hunks)
  • src/lib/types/index.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/payment-route.tsx (1)
src/components/ui/tooltip.tsx (1)
  • Tooltip (11-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (2)
src/components/payment-route.tsx (2)

1-1: Tooltip import looks good.

Matches the Radix-based Tooltip API used in the codebase.


3-3: Info icon import is appropriate.

Icon is used as a discrete tooltip trigger.

Copy link
Contributor

@bassgeta bassgeta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good 😎
image

@rodrigopavezi
Copy link
Member Author

Screenshot 2025-09-27 at 05 51 30

@rodrigopavezi
Copy link
Member Author

Screenshot 2025-09-29 at 22 48 28 Screenshot 2025-09-29 at 22 48 46 Screenshot 2025-09-29 at 22 48 37

@rodrigopavezi
Copy link
Member Author

Screenshot 2025-09-30 at 16 24 09

Copy link
Contributor

@bassgeta bassgeta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, nice and simple 💯
🚢 before I merge that big ecommerce chonker PR and potentially cause conflicts 😅

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/payment-route.tsx (1)

18-21: Remove unused platformFee prop from interface.

The platformFee property is defined in the PaymentRouteProps interface but is never destructured or used within the component. This is dead code that should be removed.

Apply this diff to remove the unused prop:

 interface PaymentRouteProps {
   route: PaymentRouteType;
   isSelected: boolean;
   onClick?: () => void;
   variant?: "default" | "selected";
   routeType?: RouteTypeInfo;
-  platformFee?: {
-    percentage: number;
-    address: string;
-  };
 }
♻️ Duplicate comments (1)
src/components/payment-route.tsx (1)

159-167: CRITICAL: Nested button breaks accessibility (unresolved from previous review).

The nested button issue flagged in the previous review remains unresolved. You still have a <button> element nested inside the PaymentRoute <button>, which violates HTML semantics and breaks keyboard navigation for screen reader users.

You claimed this was fixed, but the element is still a <button> instead of a <span> with proper ARIA attributes and keyboard handling.

Apply this diff to properly fix the accessibility issue:

-                      <button
-                        type="button"
+                      <span
+                        role="button"
+                        tabIndex={0}
                         aria-label="Show fee breakdown"
-                        className="text-zinc-400 hover:text-zinc-600 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-zinc-400 rounded"
+                        className="text-zinc-400 hover:text-zinc-600 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-zinc-400 rounded cursor-pointer"
-                        onClick={(e) => e.stopPropagation()}
+                        onClick={(e) => e.stopPropagation()}
+                        onKeyDown={(e) => {
+                          if (e.key === "Enter" || e.key === " ") {
+                            e.preventDefault();
+                            e.stopPropagation();
+                          }
+                        }}
                       >
                         <Info className="w-3 h-3" aria-hidden="true" />
-                      </button>
+                      </span>
🧹 Nitpick comments (2)
src/components/payment-route.tsx (2)

72-104: Consider improving key uniqueness and amount formatting.

The formatFeeBreakdown function is well-structured, but consider these refinements:

  1. Key uniqueness: The key ${fee.type}-${fee.provider}-${fee.stage} might not be unique if multiple fees share the same values. Consider adding an index or using a unique identifier if available.

  2. Decimal precision: .toFixed(6) may show excessive precision for typical fee amounts. Consider using .toFixed(2) or a dynamic precision based on the amount magnitude.

  3. Null safety: Add a guard for fee.amountInUSD to handle potential undefined values.

Apply this diff to improve the implementation:

-        {route.feeBreakdown.map((fee) => (
+        {route.feeBreakdown.map((fee, index) => (
           <div
-            key={`${fee.type}-${fee.provider}-${fee.stage}`}
+            key={`${fee.type}-${fee.provider}-${fee.stage}-${index}`}
             className="flex justify-between items-start text-xs"
           >
             <div className="flex-1">
               <div className="capitalize font-medium">
                 {fee.type === "gas"
                   ? "Gas Fee"
                   : fee.type === "crosschain"
                     ? "Crosschain Fee"
                     : "Platform Fee"}
               </div>
             </div>
             <div className="text-right ml-2">
               <div className="font-medium">
-                {Number(fee.amountInUSD).toFixed(6)} USD
+                {fee.amountInUSD != null ? Number(fee.amountInUSD).toFixed(2) : 'N/A'} USD
               </div>
             </div>
           </div>
         ))}

154-154: Simplify the optional chaining pattern.

The expression Number(route?.feeInUSD)?.toFixed(6) has redundant optional chaining. Number() always returns a number (or NaN for invalid input), never undefined, so the second ?. serves no purpose.

Consider this clearer approach:

-                  {Number(route?.feeInUSD)?.toFixed(6)} USD fee
+                  {(route.feeInUSD != null ? Number(route.feeInUSD).toFixed(2) : '0.00')} USD fee

This also reduces the decimal precision to 2 places, which is more appropriate for displaying USD amounts.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38c2521 and 3618c20.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/app/globals.css (2 hunks)
  • src/components/payment-route.tsx (3 hunks)
  • src/lib/types/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/types/index.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/payment-route.tsx (1)
src/components/ui/tooltip.tsx (1)
  • Tooltip (11-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (1)
src/app/globals.css (1)

10-11: Confirm popover color inversion aligns with design. Contrast is ≈ 19:1 (exceeds WCAG 2.1 AA/AAA); verify all popovers render correctly and consistently across light and dark themes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EasyInvoice - Fee Breakdown on Payment Page before payment
2 participants